#include "syntax_parser.h"
#include "errors_warnings.h"

#include "main_container.h"
extern MainContainer * CompilerData;


// <while_statement> ~ while ( <expression> ) <block_statement>  {while}
void Parser::Parse_WhileStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_WhileStatement");
#endif
    LexicUnit unit;

    // get current lexic unit
    unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

    // check if and which production we can apply
    if(unit.type == LUTypeKeyword && unit.subtype == KeywordWhile)
    {
        //	write type of production in this node
        parent->Production = Gr_WhileStatement__while_spLPar_Expression_spRPar_BlockStatement;

        // process terminal symbol 'while'
        SyntaxTreeNode * newNode = new SyntaxTreeNode();
        parent->Nodes->Add(newNode);
        newNode->LexUnitID=this->CurrentLexicPosition;
        newNode->Production=Gr_Terminal;
        //increase counter
        CurrentLexicPosition++;


        // get current lexic unit - testing for '('
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterLeftParenthesis)
        {
            // process terminal symbol '('	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }

        // process nonterminal symbol '<expression>'
        SyntaxTreeNode * newExpressionNode = new SyntaxTreeNode();
        parent->Nodes->Add(newExpressionNode);
        Parse_Expression(newExpressionNode);

        // get current lexic unit - testing for ')'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterRightParenthesis)
        {
            // process terminal symbol ')'	          
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }

        // process nonterminal symbol '<block_statement>'
        SyntaxTreeNode * newStatementEndingNode = new SyntaxTreeNode();
        parent->Nodes->Add(newStatementEndingNode);
        Parse_BlockStatement(newStatementEndingNode);

    }
    else
    {
        // ERROR has been found
        // REPORT ERROR
        CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_WHILE_STATEMENT_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
    }
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_WhileStatement");
#endif
}


// <dowhile_statement> ~ do <block_statement> while ( <expression> ) ;  {do}
void Parser::Parse_DowhileStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_DowhileStatement");
#endif
    LexicUnit unit;

    // get current lexic unit
    unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

    // check if and which production we can apply
    if(unit.type == LUTypeKeyword && unit.subtype == KeywordDo)
    {
        //	write type of production in this node
        parent->Production = Gr_DowhileStatement__do_BlockStatement_while_spLPar_Expression_spRPar_spSemiCol;

        // process terminal symbol 'do'
        SyntaxTreeNode * newNode = new SyntaxTreeNode();
        parent->Nodes->Add(newNode);
        newNode->LexUnitID=this->CurrentLexicPosition;
        newNode->Production=Gr_Terminal;
        //increase counter
        CurrentLexicPosition++;

        // process nonterminal symbol '<block_statement>'
        SyntaxTreeNode * newStatementEndingNode = new SyntaxTreeNode();
        parent->Nodes->Add(newStatementEndingNode);
        Parse_BlockStatement(newStatementEndingNode);


        // get current lexic unit - testing for 'while'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeKeyword && unit.subtype == KeywordWhile)
        {
            // process terminal symbol 'while'	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_WHILE_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }


        // get current lexic unit - testing for '('
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterLeftParenthesis)
        {
            // process terminal symbol '('
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }

        // process nonterminal symbol '<expression>'
        SyntaxTreeNode * newExpressionNode = new SyntaxTreeNode();
        parent->Nodes->Add(newExpressionNode);
        Parse_Expression(newExpressionNode);

        // get current lexic unit - testing for ')'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterRightParenthesis)
        {
            // process terminal symbol ')'	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }

        // get current lexic unit - testing for ';'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterSemicolon)
        {
            // process terminal symbol ';'	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_SEMICOLON_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }

    }
    else
    {
        // ERROR has been found
        // REPORT ERROR
        CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_DOWHILE_STATEMENT_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
    }
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_DowhileStatement");
#endif
}

// <for_statement> ~ for ( <simple_statement> ; <expression> ; <simple_statement> ) <block_statement>  {for}
void Parser::Parse_ForStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ForStatement");
#endif
    LexicUnit unit;

    // get current lexic unit
    unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

    // check if and which production we can apply
    if(unit.type == LUTypeKeyword && unit.subtype == KeywordFor)
    {
        //	write type of production in this node
        parent->Production = Gr_ForStatement__for_spLPar_SimpleStatement_spSemiCol_Expression_spSemiCol_SimpleStatement_spRPar_BlockStatement;

        //obradi završni znak 'for'	
        SyntaxTreeNode * newNode = new SyntaxTreeNode();
        parent->Nodes->Add(newNode);
        newNode->LexUnitID=this->CurrentLexicPosition;
        newNode->Production=Gr_Terminal;
        //increase counter
        CurrentLexicPosition++;

        // get current lexic unit - testing for '('
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterLeftParenthesis)
        {
            // process terminal symbol '('	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }

        // process nonterminal symbol '<simple_Statement>'
        SyntaxTreeNode * newSimpleStatement1 = new SyntaxTreeNode();
        parent->Nodes->Add(newSimpleStatement1);
        Parse_SimpleStatement(newSimpleStatement1);


        // get current lexic unit - testing for ';'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterSemicolon)
        {
            // process terminal symbol ';'	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_SEMICOLON_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }

        // process nonterminal symbol '<expression>'
        SyntaxTreeNode * newExpression = new SyntaxTreeNode();
        parent->Nodes->Add(newExpression);
        Parse_Expression(newExpression);


        // get current lexic unit - testing for ';'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterSemicolon)
        {
            // process terminal symbol ';'	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_SEMICOLON_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }

        
        // process nonterminal symbol '<simple_Statement>'
        SyntaxTreeNode * newSimpleStatement2 = new SyntaxTreeNode();
        parent->Nodes->Add(newSimpleStatement2);
        Parse_SimpleStatement(newSimpleStatement2);


        // get current lexic unit - testing for ')'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterRightParenthesis)
        {
            // process terminal symbol ')'	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }

        
        // process nonterminal symbol '<block_statement>'
        SyntaxTreeNode * newStatementEndingNode = new SyntaxTreeNode();
        parent->Nodes->Add(newStatementEndingNode);
        Parse_BlockStatement(newStatementEndingNode);

    }
    else
    {
        // ERROR has been found
        // REPORT ERROR
         CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_FOR_STATEMENT_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
    }
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ForStatement");
#endif
}

// <break_statement> ~ break ;  {break}
void Parser::Parse_BreakStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_BreakStatement");
#endif
    LexicUnit unit;

    // get current lexic unit
    unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

    // check if and which production we can apply
    if(unit.type == LUTypeKeyword && unit.subtype == KeywordBreak)
    {
        //	write type of production in this node
        parent->Production = Gr_BreakStatement__break_spSemiCol;

        // process terminal symbol 'break'	
        SyntaxTreeNode * newBreakNode = new SyntaxTreeNode();
        parent->Nodes->Add(newBreakNode);
        newBreakNode->LexUnitID=this->CurrentLexicPosition;
        newBreakNode->Production=Gr_Terminal;
        //increase counter
        CurrentLexicPosition++;

        // get current lexic unit - testing for ';'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterSemicolon)
        {
            // process terminal symbol ';'	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_SEMICOLON_MATCH);
            //increase counter
            CurrentLexicPosition++;
        } 

    }
    else
    {
        // ERROR has been found
        // REPORT ERROR
        CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_BREAK_STATEMENT_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
    }
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_BreakStatement");
#endif
}

// <continue_statement> ~ continue ;  {continue}
void Parser::Parse_ContinueStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ContinueStatement");
#endif
    LexicUnit unit;

    // get current lexic unit
    unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

    // check if and which production we can apply
    if(unit.type == LUTypeKeyword && unit.subtype == KeywordContinue)
    {
        //	write type of production in this node
        parent->Production = Gr_ContinueStatement__continue_spSemiCol;

        // process terminal symbol 'continue'	
        SyntaxTreeNode * newContinueNode = new SyntaxTreeNode();
        parent->Nodes->Add(newContinueNode);
        newContinueNode->LexUnitID=this->CurrentLexicPosition;
        newContinueNode->Production=Gr_Terminal;
        //increase counter
        CurrentLexicPosition++;


        // get current lexic unit - testing for ';'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterSemicolon)
        {
            // process terminal symbol ';'	
            
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_SEMICOLON_MATCH);
            //increase counter
            CurrentLexicPosition++;
        } 

    }
    else
    {
        // ERROR has been found
        // REPORT ERROR
        CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_CONTINUE_STATEMENT_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
    }
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ContinueStatement");
#endif
}

// <goto_statement> ~ goto NAME ;  {goto}
void Parser::Parse_GotoStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_GotoStatement");
#endif
    LexicUnit unit;

    // get current lexic unit
    unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

    // check if and which production we can apply
	if(unit.type == LUTypeKeyword && unit.subtype == KeywordGoto)
    {
        //	write type of production in this node
        parent->Production = Gr_GotoStatement__goto_NAME_spSemiCol;

        // process terminal symbol 'goto'	
        SyntaxTreeNode * newGotoNode = new SyntaxTreeNode();
        parent->Nodes->Add(newGotoNode);
        newGotoNode->LexUnitID=this->CurrentLexicPosition;
        newGotoNode->Production=Gr_Terminal;
        //increase counter
        CurrentLexicPosition++;


        // process terminal symbol 'NAME' 
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if(unit.type == LUTypeIdentifier)
        {
            SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode1);
            newNode1->LexUnitID=this->CurrentLexicPosition;
            newNode1->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
        else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_NAME_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }   



        // get current lexic unit - testing for ';'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterSemicolon)
        {
            // process terminal symbol ';'	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_SEMICOLON_MATCH);
            //increase counter
            CurrentLexicPosition++;
        } 

    }
    else
    {
        // ERROR has been found
        // REPORT ERROR
        CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_GOTO_STATEMENT_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
    }
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_GotoStatement");
#endif
}

// <start_assignments> ~ <start_assignment> <start_assignment_add>  {NAME}
void Parser::Parse_StartAssignments(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_StartAssignments");
#endif
    LexicUnit unit;

    // get current lexic unit
    unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

    // check if and which production we can apply
    if(unit.type == LUTypeIdentifier)
    {
        //	write type of production in this node
        parent->Production = Gr_StartAssignments__StartAssignment_StartAssignmentAdd;


        // process nonterminal symbol '<start_assignment>'
        SyntaxTreeNode * newStartAssignment = new SyntaxTreeNode();
        parent->Nodes->Add(newStartAssignment);
        Parse_StartAssignment(newStartAssignment);


        // process nonterminal symbol '<start_assignment_add>'
        SyntaxTreeNode * newStartAssignmentAdd = new SyntaxTreeNode();
        parent->Nodes->Add(newStartAssignmentAdd);
        Parse_StartAssignmentAdd(newStartAssignmentAdd);

    }
    else
    {
        // ERROR has been found
        // REPORT ERROR
        CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_START_ASSIGNMENTS_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
    }
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_StartAssignments");
#endif
}

// <start_assignment_add> ~ <start_assignment_comma_add> <start_assignment_add>  {,}
// <start_assignment_add> ~ ? {;}
void Parser::Parse_StartAssignmentAdd(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_StartAssignmentAdd");
#endif
    LexicUnit unit;

    do
    {
        // get current lexic unit
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

        // ako se lekisčka jedinka nalazi u skupu Primjeni produkcije koja nije epsilon {,} 
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterComma)
        {
            //	write type of production in this node
            parent->Production = Gr_StartAssignmentAdd__StartAssignmentCommaAdd_StartAssignmentAdd;

            //	Napravi čvor dijete i dodaj ga roditelju
            //  Pozovi metodu koja će obraditi NZ s desne strane		
            SyntaxTreeNode * newNode = new SyntaxTreeNode();
            parent->Nodes->Add(newNode);
            Parse_StartAssignmentCommaAdd(newNode);
        }

        // if current lexic unit is in the select set of {;}
        else if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterSemicolon)
        {
            // this is epsilon part of production
            parent->Production = Gr_StartAssignmentAdd__StartAssignmentCommaAdd_StartAssignmentAdd;

            // new node is not needed
            break;

        }

        // the current lexical symbol was not found matching any production
        else
        {
            // ERROR has been found
            // REPORT ERROR
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_START_ASSIGNMENT_ADD_BEGINING);
            // This is recovoring from error
            this->CurrentLexicPosition++;
            break;

        }


    }
    while(1);

#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_StartAssignmentAdd");
#endif
}

// <start_assignment_comma_add> ~ , <start_assignment>  {,}
void Parser::Parse_StartAssignmentCommaAdd(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_StartAssignmentCommaAdd");
#endif
    LexicUnit unit;

    // get current lexic unit
    unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

    // check if and which production we can apply
    if(unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterComma)
    {
        //	write type of production in this node
        parent->Production = Gr_StartAssignmentCommaAdd__spComma_StartAssignment;

        // process terminal symbol ','
        SyntaxTreeNode * newCommaNode = new SyntaxTreeNode();
        parent->Nodes->Add(newCommaNode);
        newCommaNode->LexUnitID=this->CurrentLexicPosition;
        newCommaNode->Production=Gr_Terminal;
        //increase counter
        CurrentLexicPosition++;

        // process nonterminal symbol '<start_assignment>'
        SyntaxTreeNode * newStartAssignment = new SyntaxTreeNode();
        parent->Nodes->Add(newStartAssignment);
        Parse_StartAssignment(newStartAssignment);

    }
    else
    {
        // ERROR has been found
        // REPORT ERROR
        CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_START_ASSIGNMENT_COMMA_ADD_BEGINING);
        // This is recovoring from error
        this->CurrentLexicPosition++;
    }
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_StartAssignmentCommaAdd");
#endif
}

// <start_assignment> ~ NAME = <expression>  {NAME}
void Parser::Parse_StartAssignment(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_StartAssignment");
#endif
    LexicUnit unit;

    // get current lexic unit
    unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

    // check if and which production we can apply
    if(unit.type == LUTypeIdentifier)
    {
        //	write type of production in this node
        parent->Production = Gr_StartAssignment__NAME_opAssign_Expression;

        // process terminal symbol 'NAME'
        SyntaxTreeNode * newIdentifierNode = new SyntaxTreeNode();
        parent->Nodes->Add(newIdentifierNode);
        newIdentifierNode->LexUnitID=this->CurrentLexicPosition;
        newIdentifierNode->Production=Gr_Terminal;
        //increase counter
        CurrentLexicPosition++;

        // get current lexic unit - testing for '='
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeOperator && unit.subtype == OperatorAssigment)
        {
            // process terminal symbol '='	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_ASSIGNMENT_MATCH);
            //increase counter
            CurrentLexicPosition++;
        } 


        // process nonterminal symbol '<expression>'
        SyntaxTreeNode * newExpression = new SyntaxTreeNode();
        parent->Nodes->Add(newExpression);
        Parse_Expression(newExpression);

    }
    else
    {
        // ERROR has been found
        // REPORT ERROR
        CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_START_ASSIGNMENT_BEGINING);
        // This is recovoring from error
        this->CurrentLexicPosition++;
    }
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_StartAssignment");
#endif
}

// <stop_statement> ~ stop <name> ;  {stop}
void Parser::Parse_StopStatement(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_StopStatement");
#endif
    LexicUnit unit;

    // get current lexic unit
    unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

    // check if and which production we can apply
    if(unit.type == LUTypeKeyword && unit.subtype == KeywordStop)
    {
        //	write type of production in this node
        parent->Production = Gr_StopStatement__stop_Name_spSemiCol;

        // process terminal symbol 'stop'
        SyntaxTreeNode * newStopNode = new SyntaxTreeNode();
        parent->Nodes->Add(newStopNode);
        newStopNode->LexUnitID=this->CurrentLexicPosition;
        newStopNode->Production=Gr_Terminal;
        //increase counter
        CurrentLexicPosition++;

		// process nonterminal symbol <name>
		SyntaxTreeNode * newName = new SyntaxTreeNode();
        parent->Nodes->Add(newName);
		Parse_Name(newName);

        
        // get current lexic unit - testing for ';'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterSemicolon)
        {
            // process terminal symbol ';'	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_SEMICOLON_MATCH);
            //increase counter
            CurrentLexicPosition++;
        } 

    }
    else
    {
        // ERROR has been found
        // REPORT ERROR
        CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_STOP_STATEMENT_BEGINING);
        // This is recovoring from error
        this->CurrentLexicPosition++;
    }
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_StopStatement");
#endif
}

// <assignment_derivation> ~ derivation <variable_value> = <expression> ;  {derivation}
void Parser::Parse_AssignmentDerivation(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_AssignmentDerivation");
#endif
    LexicUnit unit;

    // get current lexic unit
    unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

    // check if and which production we can apply
    if(unit.type == LUTypeKeyword && unit.subtype == KeywordDerivation)
    {
        //	write type of production in this node
        parent->Production = Gr_AssignmentDerivation__derivation_VariableValue_opAssign_Expression_spSemiCol;

        // process terminal symbol 'derivation'
        SyntaxTreeNode * newDerivationNode = new SyntaxTreeNode();
        parent->Nodes->Add(newDerivationNode);
        newDerivationNode->LexUnitID=this->CurrentLexicPosition;
        newDerivationNode->Production=Gr_Terminal;
        //increase counter
        CurrentLexicPosition++;


        // process nonterminal symbol '<variable_value>'
        SyntaxTreeNode * newVariableValueNode = new SyntaxTreeNode();
        parent->Nodes->Add(newVariableValueNode);
        Parse_VariableValue(newVariableValueNode);


        // get current lexic unit - testing for '='
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeOperator && unit.subtype == OperatorAssigment)
        {
            // process terminal symbol '='	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_ASSIGNMENT_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }

        // process nonterminal symbol '<expression>'
        SyntaxTreeNode * newExpressionNode = new SyntaxTreeNode();
        parent->Nodes->Add(newExpressionNode);
        Parse_Expression(newExpressionNode);

        // get current lexic unit - testing for ';'
        unit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
        if (unit.type == LUTypeSpecialCharacter && unit.subtype == SpecialCharacterSemicolon)
        {
            // process terminal symbol ';'	
            SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
            parent->Nodes->Add(newNode2);
            newNode2->LexUnitID=this->CurrentLexicPosition;
            newNode2->Production=Gr_Terminal;
            //increase counter
            CurrentLexicPosition++;
        }
       	else
        {
            //report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_SEMICOLON_MATCH);
            //increase counter
            CurrentLexicPosition++;
        }


    }
    else
    {
        // ERROR has been found
        // REPORT ERROR
        CompilerData->ErrorWarningReport->ReportError(&unit, ERR_SYN_NO_ASSIGNMENT_DERIVATION_BEGINING);
        // This is recovoring from error
        this->CurrentLexicPosition++;
    }
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_AssignmentDerivation");
#endif
}
